package com.wwj.study.spring.formework.webmvc;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Map;

public class WHandleAdapter {

    private Map<String,Integer> map;

    public WHandleAdapter(Map<String, Integer> map) {
        this.map = map;
    }

    //执行Controller方法
    //主要是拼装方法参数
    public WModelAndView handle(HttpServletRequest req, HttpServletResponse resp, WHandleMapping handler) throws Exception {
        //决定方法重载的要素：方法名称，参数个数，参数类型，参数顺序
        //1、获取执行方法主体的参数
        Class<?>[] parameterTypes = handler.getMethod().getParameterTypes();

        //2、获取url请求的参数列表
        Map<String, String[]> reqParameterMap = req.getParameterMap();

        //方法调用需要传入的实参列表
        Object[] paramValues = new Object[parameterTypes.length];
        //3、循环获取url参数
        for (Map.Entry<String, String[]> p : reqParameterMap.entrySet()) {
            String arrayStr = Arrays.toString(p.getValue());
            String value = arrayStr.replaceAll("\\[|\\]", "").replaceAll("\\s", "");
            String key = p.getKey();
            //参数位置，很重要，根据参数名称，获取对应参数位置。
            Integer index = map.get(key);
            //某个位置，放入具体的value值，value需要进行类型转换
            paramValues[index] = cashStringValue(value, parameterTypes[index]);//根据参数位置，获取参数类型
        }

        if (this.map.containsKey(HttpServletRequest.class.getName())) {
            int reqIndex = this.map.get(HttpServletRequest.class.getName());
            paramValues[reqIndex] = req;
        }

        if (this.map.containsKey(HttpServletResponse.class.getName())) {
            int repsIndex = this.map.get(HttpServletResponse.class.getName());
            paramValues[repsIndex] = resp;
        }

        Object result = handler.getMethod().invoke(handler.getController(), paramValues);
        if (result == null) {
            return null;
        }

        //返回ModelAndView
        boolean isModelAndView = handler.getMethod().getReturnType() == WModelAndView.class;
        if (isModelAndView) {
            return (WModelAndView) result;
        } else {
            return null;
        }
    }

    private Object cashStringValue(String value, Class<?> parameterType) {
        if(parameterType==String.class){
            return value;
        }else if(parameterType==Integer.class){
            return Integer.parseInt(value);
        }else if (parameterType==int.class){
            return Integer.parseInt(value);
        }else{
            return null;
        }
    }
}
